/*
 * RMI demo
 * Spring 2013 TCSS 558
 * Daniel M. Zimmerman
 */

package rmi;

import java.io.Serializable;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;

/**
 * A remote map.
 * 
 * @author Daniel M. Zimmerman
 * @version Spring 2013
 */
public class UnicastRemoteMap implements RemoteMap
{
  /**
   * The actual remote map being exported (to avoid garbage 
   * collection).
   */
  private static RemoteMap static_map;
  
  /**
   * The minimum acceptable port number.
   */
  private static final int MIN_PORT = 1025;
  
  /**
   * The maximum acceptable port number.
   */
  private static final int MAX_PORT = 65535;
  
  /**
   * The HashMap encapsulated by this RemoteMap.
   */
  private final Map<Serializable, Serializable> my_map = 
    new HashMap<Serializable, Serializable>();  
  
  @Override
  public Serializable put(final Serializable the_key, 
                          final Serializable the_value)
    throws RemoteException
  {
    System.err.println("mapping " + the_key + " to " + the_value);
    return my_map.put(the_key, the_value);   
  }
  
  @Override
  public Serializable get(final Serializable the_key) 
    throws RemoteException
  {
    System.err.println("returning the mapped value for " + the_key);
    return my_map.get(the_key);
  }
  
  @Override
  public void clear() throws RemoteException
  {
    System.err.println("clearing the map");
    my_map.clear();
//    while (true)
//    {
//      // eek!
//    }
  }
  
  /**
   * The main() method. Creates a new RemoteMap and binds it
   * to the name "RemoteMap" on an RMI registry with the port
   * specified in the command line argument.
   * 
   * @param the_args The first argument is the port number; 
   * all others are ignored.
   */
  public static void main(final String[] the_args)
  {
    try
    {
      final int port = Integer.parseInt(the_args[0]);
      if (port < MIN_PORT || MAX_PORT < port)
      {
        System.err.println("port must be between 1025 and 65535 inclusive");
        System.exit(1);
      }
      
      final Registry registry = LocateRegistry.createRegistry(port);
      static_map = new UnicastRemoteMap();
      registry.bind("RemoteMap", UnicastRemoteObject.exportObject(static_map, 0));
      System.err.println("remote map listening on port " + port);
    }
    catch (final AccessException e)
    {
      System.err.println("issue accessing registry: " + e);
      System.exit(1);
    }
    catch (final AlreadyBoundException e)
    {
      System.err.println("already bound???: " + e);
      System.exit(1);
    }
    catch (final RemoteException e)
    {
      System.err.println("a problem occurred: " + e);
      System.exit(1);
    }
  }
}
